package com.cinyi.cyds.base.mongo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import com.cinyi.cyds.base.module.BaseModule;
import com.cinyi.cyds.util.ConfigUtil;
import com.mongodb.DBObject;

/**
 * 存储mongodb的实现类<br>
 * @author penghui
 *
 */
public class MongoManager extends BaseModule {
	private static final String TAG = "MongoStoreManager" ;
	
	private static final Logger Log = Logger.getLogger(MongoManager.class); 
	
	private static final long TIMER_DELAY = 5000L ;

	private long delayTime = TIMER_DELAY ;
	
	/**
	 * 定时任务执行对象
	 */
	private ScheduledExecutorService scheduExec = Executors.newScheduledThreadPool(1);  
	
	/**
	 * 根据名称缓存要保存的存储记录集
	 */
	private Map<String, List<DBObject>> cache0;
	
	private static MongoManager instance = null ;
	
	private MongoHelper mongo = null ;
	public static MongoManager getInstance(){
		if(instance == null){
			instance = new MongoManager();
		}
		return instance ;
	}
	
	private MongoManager() {
	}

    private void initialize() {
		delayTime = ConfigUtil.getLongProperty("message.storage.delay", TIMER_DELAY ) ;
		
		cache0 = new ConcurrentHashMap<>();
		
		mongo = new MongoHelper();
		
		StoreTask task = new StoreTask();
		scheduExec.scheduleWithFixedDelay(task, 1000, delayTime, TimeUnit.MILLISECONDS);
    }

    public void destroy() {
		scheduExec.shutdown();
		scheduExec = null ;
		mongo.close();
    }
    
    public synchronized void addObject(IMongoModel obj){
    	if(obj == null||obj.toDBObject() == null ){
    		return ;
    	}
    	addDBObject(cache0,obj.getName(),obj.toDBObject());
    }
    
    private synchronized void addDBObject(Map<String, List<DBObject>> cache,String name,DBObject obj) {
    	List<DBObject> messagesCache = cache.get(name);
    	if(messagesCache == null ){
    		messagesCache = new Vector<DBObject>();
    		cache.put(name, messagesCache);
    	}
    	
    	messagesCache.add(obj);
    }
	
	class StoreTask extends TimerTask{
		@Override
		public void run() {
			save();
		}  
	}
	
	public synchronized void save() { 
		storeCache(cache0 );
	}
	
	public synchronized void storeCache(Map<String, List<DBObject>> cache){
		Iterator<String> it = cache.keySet().iterator();
		while(it.hasNext()){
			String key = it.next() ;
			List<DBObject> messagesCache = cache.get(key);
			int size = messagesCache.size() ;
			Log.info("# mongo save db name:" + key + ",size:" + size );
			if( size > 0 ){
				try{
				    mongo.insertDocuments(key,messagesCache);
				    messagesCache.clear();
				} catch(Exception ex){
					ex.printStackTrace();
					Log.error("# mongo save error:" + ex.getMessage() ) ;
				} 
			}
		}
	}

	public void start() {
		Log.info("# mongo manager start. " );
		initialize();
	}

    @Override
    public String getName()
    {
        return "mongo-module";
    }
	
}

